<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>

  <body>
    <div id="app">
      <p>{{ message }}</p>
      <input type="text" id="input" />
    </div>

    <p></p>
    <ul></ul>
    <script>
      //       惰性求值
      //       惰性求值的好处
      // 动态计算属性值：每次访问属性时都会计算最新的值，而不是在属性定义时就固定下来。这在属性值需要基于某些动态状态或上下文变化时非常有用。
      // 性能优化：惰性求值可以延迟计算，避免在属性定义时进行不必要的计算，只有在实际访问属性时才进行计算。
      let counter = 0;
      const objj = {
        name: () => `key_${counter++}`,
      };

      const exports = {};
      for (const key in objj) {
        Object.defineProperty(exports, key, {
          enumerable: true,
          get: objj[key],
        });
      }

      console.log(exports.name); // 输出: "key_0" get会根据counter的变化来动态计算  如果是value 则调用时值就会被固定不会变化输出0
      console.log(exports.name); // 输出: "key_1" get会根据counter的变化来动态计算  如果是value 则调用时值就会被固定不会变化输出0
      console.log(exports.name); // 输出: "key_2" get会根据counter的变化来动态计算  如果是value 则调用时值就会被固定不会变化输出0

      // //     console.log(Object.keys(objj));
      // //     console.log(Object.values(objj));

      //     // 将key vlaue变为数组保存
      //     //  [key:value]
      //     console.log(Object.entries(objj));
      //     // 用于 Map
      //     const map = new Map(Object.entries(objj));
      //     console.log(map);

      //        // 将数组key vlaue变为对象
      //   const arr=[['name','age'],["age",18]]
      //   console.log(Object.fromEntries(arr));

      //     var obj = {
      //         id: 1,
      //         name: '小米'
      //     }

      //     // 以前修改对象的方法时
      //     // obj.name = '华为';
      //     // obj.price = 1000;
      //     // console.log(obj);
      //     // 现在新增方法 defineproperty() 有就修改 没有就增加
      //     // defineproperty(修改的对象名字， 对项属性, 描述 （以对象方式修改）)
      //     Object.defineProperty(obj, 'price', {
      //         value: 1000,
      //         enumerable: true
      //     });

      //     Object.defineProperty(obj, 'name', {
      //         value: '华为',
      //         enumerable: false //不让遍历 默认false
      //     });
      //     console.log(Object.keys(obj), '不能遍历出name属性', obj);

      //     Object.defineProperty(obj, 'id', {
      //         writable: false //不允许修改数值 默认是false
      //     });
      //     obj.id = 5;
      //     console.log(obj, '不会更改id的值');

      //     Object.defineProperty(obj, 'address', {
      //         value: '中国山东蓝翔',
      //         writable: false, //如果是false 不允许修改这个属性值
      //         enumerable: false, //不让遍历 ，
      //         configurable: false //如果是false 不允许删除这个属性值 不允许修改其他属性值enumerable，writable
      //     });

      //     // 错误 configurable 为false就不允许再次更改
      //     // Object.defineProperty(obj, 'address', {
      //     //     value: '中国山东蓝翔',
      //     //     writable: true,
      //     //     enumerable: true, //不让遍历 ，
      //     //     configurable: true //是否可以被删除会报错
      //     // });

      //     delete obj.address;
      //     delete obj.name; //删除成功
      //     console.log(obj, '删除name');

      //     let newname = obj.name
      //     Object.defineProperty(obj, 'name', {
      //         get() {
      //             console.log('正在访问obj的name');
      //             return newname
      //         }, //访问对象值触发

      //         set(value) {
      //             // value拿到最新的值
      //             console.log('改变name值 ' + value);
      //             // obj.name=value
      //         }, //设置新值触发 vue2 的响应原理

      //     });

      //     obj.name = 'zks'
      // //   console.log( obj.name);

      //     // vue框架的使用 双向绑定原理

      // 数据对象
      const data = {
        message: "双向绑定原理",
      };

      // 观察者函数
      function observe(obj) {
        for (let key in obj) {
          if (obj.hasOwnProperty(key)) {
            let value = obj[key];
            Object.defineProperty(obj, key, {
              get() {
                return value;
              },
              set(newValue) {
                value = newValue;
                updateView();
              },
            });
          }
        }
      }

      // 更新视图
      function updateView() {
        const messageElement = document.querySelector("#app p");
        messageElement.textContent = data.message;

        const inputElement = document.querySelector("#input");
        inputElement.value = data.message;
      }

      // 初始化
      observe(data);
      updateView();
      // 监听输入框变化，更新数据
      const inputElement = document.querySelector("#input");
      inputElement.addEventListener("input", function (event) {
        data.message = event.target.value;
      });
    </script>
  </body>
</html>
